use crate::data::cpu::CpuData;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

use crate::data::route::IPRouteTable;
use crate::helper::{exists_value_from_vec, extract_data, extract_with_position};
use crate::snmptrapd::get_trap_lines;

use super::{interface::NetworkInterface, memory::Memory, protocol::ProtocolStatistic};

#[derive(Debug, Serialize, Deserialize, Default, JsonSchema, Clone)]
pub struct DeviceInfo {
    pub interfaces: Vec<NetworkInterface>,
    pub memory_infos: Vec<Memory>,
    pub route_list: Vec<IPRouteTable>,
    pub cpu: CpuData,
    /// 设备名称
    ///
    /// SNMPv2-MIB::sysName  - 1.3.6.1.2.1.1.5
    pub name: String,
    /// 运行时间
    ///
    /// DISMAN-EVENT-MIB::sysUpTimeInstance  - 1.3.6.1.2.1.1.3.0
    pub uptime: String,
    /// 端口数
    ///
    /// IF-MIB::ifNumber - 1.3.6.1.2.1.2.1
    pub port_num: String,
    /// 设备描述
    ///
    /// 3.6.1.2.1.1.9.1.3.5 = STRING: "Agent capabilities for the BRIDGE-MIB
    ///
    /// SNMPv2-MIB::sysDescr - 1.3.6.1.2.1.1.1
    pub describe: String,
    /// 系统OID
    ///
    /// SNMPv2-MIB::sysObjectID - 1.3.6.1.2.1.1.2
    pub sys_object_id: String,
    ///  服务数量
    ///
    /// SNMPv2-MIB::sysServices iso.3.6.1.2.1.1.7.0
    pub service_count: String,
    /// 网口默认TTL
    ///
    /// TTL ipDefaultTTL .3.6.1.2.1.4.2
    pub default_ttl: String,
    /// 网口队列接收分片最大缓冲时间
    ///
    /// IP-MIB::ipReasmTimeout. .3.6.1.2.1.4.13
    pub max_held_time: String,
    /// Ping响应时间
    ///
    /// IP-MIB::icmpOutTimestampReps  -  1.3.6.1.2.1.5.24
    pub ping_result: String,
    /// 序列号
    ///
    /// hillstone .3.6.1.4.1.28557.2.2.1.1.0
    ///
    /// iso.3.6.1.4.1.28557.2.2.1.1.0 = STRING: "0010029794203737"
    pub serial: String,
    /// 启动文件
    ///
    /// hillstone 3.6.1.4.1.28557.2.2.1.2.0
    ///
    /// iso.3.6.1.4.1.28557.2.2.1.2.0 = STRING: "Version 5.5 SG6000-CloudEdge-5.5R7P6 2020/06/19 14:12:44"
    pub init_filepath: String,
    /// 最大会话数
    ///
    ///
    /// 1.3.6.1.4.1.28557.2.2.1.6
    /// iso.3.6.1.4.1.28557.2.2.1.6.0 = Counter32: 1250
    pub max_sessions: String,
    /// 当前会话数量
    ///
    ///
    /// .1.3.6.1.4.1.28557.2.2.1.7
    ///
    /// iso.3.6.1.4.1.28557.2.2.1.7.0 = Gauge32: 23
    ///
    /// iso.3.6.1.4.1.2011.6.122.15.1.2.1.4.0 = Counter64: 3
    pub current_sessions: String,
    pub protocol_statistics: Vec<ProtocolStatistic>,
    /// 设备启动后的会话总数-华为
    ///
    ///
    /// iso.3.6.1.4.1.2011.6.122.15.1.2.1.1
    ///
    /// iso.3.6.1.4.1.2011.6.122.15.1.2.1.1.0 = Counter64: 101
    pub count_sessions_from_boot: String,
    /// trap 服务接收到的信息
    pub trap_lines: Vec<String>,
}

impl DeviceInfo {
    pub async fn new(value: &str) -> Self {
        let interfaces = NetworkInterface::values(value);

        pub fn parse_get_describe(value: &str) -> String {
            let splits = value
                .split(r#"iso.3.6.1.2.1.1.1.0 = STRING: ""#)
                .collect::<Vec<&str>>();
            if splits.len() > 1 {
                let describe = splits[1].split('"').collect::<Vec<&str>>();
                describe[0].to_owned()
            } else {
                "".to_owned()
            }
        }

        Self {
            cpu: CpuData::new(value),
            port_num: interfaces.len().to_string(),
            interfaces,
            name: extract_data(r#".3.6.1.2.1.1.5.0 = STRING: "(.+)""#, value),
            uptime: extract_with_position(
                r".3.6.1.2.1.1.3.0 = Timeticks: \((.*)\) (\S+)",
                value,
                2,
            ),
            protocol_statistics: ProtocolStatistic::values(value),
            describe: parse_get_describe(value),
            sys_object_id: extract_data(r".3.6.1.2.1.1.2.0 = (.+)", value),
            service_count: extract_data(r".3.6.1.2.1.1.7.0 = INTEGER: (\d+)", value),
            default_ttl: extract_data(r".3.6.1.2.1.4.2.0 = INTEGER: (\d+)", value),
            max_held_time: extract_data(r".3.6.1.2.1.4.13.0 = INTEGER: (\d+)", value),
            ping_result: extract_data(r".3.6.1.2.1.5.24.0 = Counter32: (\d+)", value),
            route_list: IPRouteTable::table_values(value),
            memory_infos: Memory::values(value),
            serial: exists_value_from_vec(vec![extract_data(
                r#".3.6.1.4.1.28557.2.2.1.1.0 = STRING: "(.+)""#,
                value,
            )]),
            init_filepath: exists_value_from_vec(vec![extract_data(
                r#".3.6.1.4.1.28557.2.2.1.2.0 = STRING: "(.+)""#,
                value,
            )]),
            max_sessions: extract_data(r".3.6.1.4.1.28557.2.2.1.6.0 = Counter32: (\d+)", value),
            current_sessions: extract_data(r".3.6.1.4.1.28557.2.2.1.7.0 = Gauge32: (\d+)", value),
            count_sessions_from_boot: extract_data(
                r".3.6.1.4.1.2011.6.122.15.1.2.1.1.0 = Counter64: (\d+)",
                value,
            ),
            trap_lines: get_trap_lines().await,
        }
    }
}
